package com.hu.bgp.client.presenter;

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.hu.bgp.client.ClientGameContext;
import com.hu.bgp.client.EventBus;
import com.hu.bgp.client.eventservice.BgpRemoteEventServiceFactory;
import com.hu.bgp.client.rpc.BgpServiceAsync;
import com.hu.bgp.framework.clientapi.Client;
import com.hu.bgp.framework.clientapi.util.Firebug;
import com.hu.bgp.shared.BoardGameMessage;

import de.novanic.eventservice.client.event.Event;
import de.novanic.eventservice.client.event.RemoteEventService;
import de.novanic.eventservice.client.event.listener.RemoteEventListener;

public class Boardgame implements PlacePresenter<BoardgamePlace>
{
	public interface Display
	{

		void setGWTModule(Element module);

		Widget asWidget();
	}

	private BoardgamePlace place;
	private Display view;
	private BgpServiceAsync bgpService;
	private EventBus eventBus;

	private RemoteEventService remoteEventService;

	@Inject
	public Boardgame(Display view, BgpServiceAsync bgpService, EventBus eventBus)
	{
		// this.remoteEventService = remoteEventService;
		this.view = view;
		this.bgpService = bgpService;
		this.eventBus = eventBus;
		// right moment?
		exportInitNameSpace();
		bind();
	}

	private void bind()
	{

	}

	private void init()
	{
		Element gameArea = DOM.createDiv();
		gameArea.setId(Client.GAMEAREA_DIV_ID);
		view.setGWTModule(gameArea);

		loadGame(place.getGameID().getGameAlias());

		Timer timerTest = new Timer()
		{
			@Override
			public void run()
			{
				if (isLoaded())
				{
					cancel();
					createListener();
					setGameIDonModule(place.getGameID().getGameID());
				}
			}
		};
		timerTest.scheduleRepeating(100);
		timerTest.run();
	}

	public void setPlace(BoardgamePlace place)
	{
		Firebug.debug(place.asURI());
		this.place = place;

	}

	public void go(HasWidgets container)
	{
		container.clear();
		container.add(view.asWidget());

		init();
	}

	private class GameDomainEventListener implements RemoteEventListener
	{
		public void apply(Event event)
		{

			if (event instanceof BoardGameMessage)
			{

				BoardGameMessage messageEvent = (BoardGameMessage) event;
				pushEvent(messageEvent.getPayload());
			}
		}
	}

	private void createListener()
	{
		bgpService.getClientGameContext(place.getGameID(), new AsyncCallback<ClientGameContext>()
		{

			public void onFailure(Throwable caught)
			{
				// TODO Handle failure properly, through Failure handle? or
				// implenmentationm right here
				Window.alert("Failure to get GAME CONTEXT!");
			}

			public void onSuccess(ClientGameContext result)
			{
				// TODO Auto-generated method stub
				remoteEventService = BgpRemoteEventServiceFactory.getInstance().getRemoteEventService();
				remoteEventService.addListener(result.getGameDomain(), new GameDomainEventListener());
			}

		});

	}

	private void loadGame(String gameAlias)
	{

		Element body = RootPanel.get().getBodyElement();
		Element head = body.getParentElement().getFirstChildElement();

		Element script = DOM.createElement("script");
		script.setAttribute("type", "text/javascript");
		script.setAttribute("language", "javascript");
		script.setAttribute("src", "/resources/" + gameAlias + "/" + gameAlias + ".nocache.js");
		head.appendChild(script);
	}

	// Start of Java native interface
	public native void exportInitNameSpace() /*-{
		if(!$wnd['bgpenv']){
			$wnd['bgpenv'] = []};
			$wnd['bgpenv'].isLoaded = false;
	}-*/;

	public native boolean isLoaded() /*-{
		return $wnd['bgpenv'].isLoaded;
	}-*/;

	public native void setGameIDonModule(String gameID) /*-{
		return $wnd['bgpenv'].isConnected(gameID);
	}-*/;

	public native void pushEvent(String payload) /*-{
		return $wnd['bgpenv'].sendRawGWTObject(payload);
	}-*/;

}
